package com.nanbei.queue;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @ClassDescription: 阻塞队列  单锁实现
 * @JdkVersion: 17
 * @Author: BaoShan.li
 * @Created: 2023/11/29 17:01
 */
public class SingleBlockingQueue<E> implements BlockingQueueInterface<E> {

    E[] array;
    int size = 0, head = 0, tail = 0;

    ReentrantLock reentrantLock = new ReentrantLock();
    Condition tailWaits = reentrantLock.newCondition();
    Condition headWaits = reentrantLock.newCondition();


    @SuppressWarnings("all")
    public SingleBlockingQueue(int capacity) {
        this.array = (E[]) new Object[capacity];
    }

    @Override
    public void offer(E e) throws InterruptedException {
        reentrantLock.lockInterruptibly();
        try {


            while (isFull()) {
                tailWaits.await();
            }
            array[tail] = e;
            if (tail + 1 == array.length) {
                tail = 0;
            } else {
                tail++;
            }
            size++;
            headWaits.signal();
        } finally {
            reentrantLock.unlock();
        }


    }

    @Override
    public void offer(E e, long timeout) throws InterruptedException {

        reentrantLock.lockInterruptibly();
        try {
            System.out.println("11111");
            long l = TimeUnit.MILLISECONDS.toNanos(timeout);

            while (isFull()) {
                if (l <= 0) {
                    return;
                }
                //该返回值 如果>0 是还剩余多少时间
                //如果<0 证明已经过了多少超时时间
                l = tailWaits.awaitNanos(l);
            }

            array[tail] = e;
            if (tail + 1 == array.length) {
                tail = 0;
            } else {
                tail++;
            }
            size++;
            headWaits.signal();
        } finally {
            reentrantLock.unlock();
        }


    }

    @Override
    public E poll() throws InterruptedException {

        reentrantLock.lockInterruptibly();
        try {
            while (isEmpty()) {
                headWaits.await();
            }

            E e = array[head];
            if (head + 1 == array.length) {
                head = 0;
            } else {
                head++;
            }
            size--;
            tailWaits.signal();
            return e;
        } finally {
            reentrantLock.unlock();
        }
    }

    @Override
    public boolean isEmpty() {
        return size == 0;
    }

    @Override
    public boolean isFull() {
        return size == array.length;
    }

    public static void main(String[] args) {

    }
}
